<script>
import { debounce, cloneDeep, isEqual } from 'lodash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ActivityFilter from '../filters/activity_filter.vue';
import ProjectFilter from '../filters/project_filter.vue';
import ClusterFilter from '../filters/cluster_filter.vue';
import ImageFilter from '../filters/image_filter.vue';
import ToolFilter from '../filters/tool_filter.vue';
import ToolWithVendorFilter from '../filters/tool_with_vendor_filter.vue';
import SeverityFilter from '../filters/severity_filter.vue';
import StatusWithDismissalFilter from '../filters/status_with_dismissal_filter.vue';
import { FILTERS } from './constants';

export default {
  mixins: [glFeatureFlagsMixin()],
  props: {
    filters: {
      type: Array,
      required: true,
    },
  },
  data() {
    return {
      filterQuery: {},
      // When this component is first shown, every filter will emit its own @filter-changed event at
      // the same time, which will trigger this method multiple times. We'll debounce it so that it
      // only runs once. Note that this is in data() so that it's unique per instance. Otherwise,
      // every instance of this component will share the same debounce function.
      emitFilterChange: debounce(function emit() {
        this.$emit('filters-changed', this.filterQuery);
      }),
    };
  },
  methods: {
    getComponentType(filter) {
      switch (filter) {
        case FILTERS.SEVERITY:
          return SeverityFilter;
        case FILTERS.STATUS:
          return StatusWithDismissalFilter;
        case FILTERS.TOOL_VENDOR:
          return ToolWithVendorFilter;
        case FILTERS.TOOL_SIMPLE:
          return ToolFilter;
        case FILTERS.TOOL_PIPELINE:
          return ToolFilter;
        case FILTERS.ACTIVITY:
          return ActivityFilter;
        case FILTERS.PROJECT:
          return ProjectFilter;
        case FILTERS.CLUSTER:
          return ClusterFilter;
        case FILTERS.IMAGE:
          return ImageFilter;
        default:
          throw new Error(`Invalid filter type: ${filter}`);
      }
    },
    updateFilterQuery(query) {
      const oldQuery = cloneDeep(this.filterQuery);
      this.filterQuery = { ...this.filterQuery, ...query };
      // Don't emit if the filters didn't change because it will trigger the GraphQL queries to run.
      if (!isEqual(oldQuery, this.filterQuery)) {
        this.emitFilterChange();
      }
    },
  },
};
</script>

<template>
  <div
    class="vulnerability-report-filters gl-p-5 gl-bg-gray-10 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
  >
    <component
      :is="getComponentType(filter)"
      v-for="filter in filters"
      :key="filter"
      @filter-changed="updateFilterQuery"
    />
  </div>
</template>
